home *** CD-ROM | disk | FTP | other *** search
- #include "main.h"
- #include "patch.h"
-
- static int modalActed = 0, modalTrapOn = 0;
- static long oldModal, oldFilterProc = NULL;
-
- /*******************************************************
- * *
- * isButtonControl is *very* dangerous. It reads the high 8 bits of the defProc *
- * pointer to figure out what type of control this is. This could be rewritten to *
- * try getResource on the CDEF resource and compare handles or something. *
- * *
- *******************************************************/
-
- isButtonControl( theControl )
- ControlHandle theControl;
- {
- return( HiWord(( **theControl ).contrlDefProc ) < 0x1000 && !( **theControl ).contrlHilite );
- }
-
- /*******************************************************
- * *
- * FindButton is used in the dialog event filters. If a command-letter combination *
- * is entered in a dialog while gadlife is running, the program attempts to find a *
- * button with that letter as its first character. If it finds one, it kills the event *
- * and returns an itemHit in the appropriate button. If there are duplicates, none *
- * are returned, and the event is passed through. This may end up causing *
- * problems with certain DA's which have command-key equivalents for buttons *
- * which do not correspond to first letters of the buttons, but this seems unlikely. *
- * *
- *******************************************************/
-
- findButton( theDialog, theChar, modifiers )
- DialogPtr theDialog;
- char theChar;
- int modifiers;
- {
- ControlHandle item = 0, control, theControl;
- Rect box;
- long finalTicks;
- int itemNo = 0, type, found;
-
- if( theChar == ETX || theChar == CR ) {
- itemNo = (( DialogPeek )theDialog )->aDefItem;
- GetDItem( theDialog, itemNo, &type, &item, &box );
- } else if( modifiers & cmdKey ) {
- if( theChar >= 'a' && theChar <= 'z' ) theChar += 'A'-'a';
- control = (( WindowPeek )theDialog )->controlList;
- for( found = 0; control && found < 2; control = ( **control ).nextControl )
- if( isButtonControl( control ) && ( **control ).contrlTitle[ 1 ] == theChar ) {
- theControl = control;
- ++found;
- }
- if( found == 1 )
- while( item != theControl )
- GetDItem( theDialog, ++itemNo, &type, &item, &box );
- }
- if( itemNo ) {
- HiliteControl( item, inButton );
- doDelay( buttonDelay, &finalTicks );
- HiliteControl( item, 0 );
- }
- return( itemNo );
- }
-
- /*******************************************************
- * *
- * FakeFilter simply replaces the usual default event filter with one which allows *
- * backgrounding and catches keyboard equivalents (using findButton). *
- * *
- *******************************************************/
-
- pascal int fakeFilter( theDialog, theEvent, itemHit )
- DialogPtr theDialog;
- EventRecord *theEvent;
- int *itemHit;
- {
- Rect box;
- ControlHandle item;
- int type, result = 0;
- char theChar;
-
- doBackground( nothingElseToDo, noGray, NULL );
- if( theEvent->what == keyDown ) {
- theChar = theEvent->message & charCodeMask;
- if( *itemHit = findButton( theDialog, theChar, theEvent->modifiers ))
- result = -1;
- }
- return( result );
- }
-
- /*******************************************************
- * *
- * PassFilter usually passes the filter call through to the original filter. If there *
- * is a keyboard shortcut, it is flagged and returned without calling the original *
- * filter. This might cause a problem with a filter that does more than just filter *
- * events. To fix, could instead pass a mouse-down and then patch TrackControl *
- * or something to immediately return true. *
- * *
- *******************************************************/
-
- pascal int passFilter( theDialog, theEvent, itemHit )
- DialogPtr theDialog;
- EventRecord *theEvent;
- int *itemHit;
- {
- char theChar;
-
- doBackground( someElseToDo, noGray, NULL );
- if( theEvent->what == keyDown ) {
- theChar = theEvent->message & charCodeMask;
- if( *itemHit = findButton( theDialog, theChar, theEvent->modifiers ))
- return( -1 );
- }
- asm {
- unlk a6
- move.l oldFilterProc,a0
- jmp (a0)
- }
- }
-
- /*******************************************************
- * *
- * If the modal dialog patches are not already installed, it doModalPatch installs *
- * them. If there is no filterProc, fakeFilter is installed. If a filterProc is given, *
- * passFilter is installed as a filter filter. This is where the problem is - If there *
- * are nested dialogs, with more than one filterproc, after the child closes the *
- * parent will still use the child's filterproc. I'm not quite sure how to fix this. *
- * *
- *******************************************************/
-
- pascal doModalPatch( theFilter, theHit )
- long theFilter;
- int *theHit;
- {
- int temp;
- asm {
- movem.l d0-d7/a1-a5,-(sp)
- move.l CurrentA5,a5
- }
- if( !modalActed ) {
- installWaitTrap();
- installPopUpTrap();
- modalActed = 1;
- }
- if( theFilter ) {
- oldFilterProc = theFilter;
- theFilter = (long)passFilter;
- } else theFilter = (long)fakeFilter;
- asm {
- move.l oldModal,a0
- movem.l (sp)+,d0-d7/a1-a5
- unlk a6
- jmp (a0)
- }
- }
-
- /*******************************************************
- * *
- * These are horrible, and need fixing. *
- * *
- *******************************************************/
-
- installModalTrap()
- {
- if( !modalTrapOn )
- {
- oldModal = NGetTrapAddress( ModalTrapNum, ToolTrap );
- NSetTrapAddress( doModalPatch, ModalTrapNum, ToolTrap );
- modalActed = 0;
- }
- ++modalTrapOn;
- }
-
- removeModalTrap() {
- if( modalTrapOn == 1 ) {
- NSetTrapAddress( oldModal, ModalTrapNum, ToolTrap );
- if( modalActed ) {
- removeWaitTrap();
- removePopUpTrap();
- modalActed = 0;
- }
- }
- if( modalTrapOn > 0 ) --modalTrapOn;
- }